mod consts;
mod evlauter;
mod object;
mod compiler;

use crate::evlauter::Env;

use linefeed::{Interface, ReadResult};
use std::cell::RefCell;
use std::path::Path;
use std::rc::Rc;

const PROMPT: &str = "rlisp> ";

fn main() {
    let args: Vec<String> = std::env::args().collect();
    match args.len() {
        1 => run_interactive(),
        2 => run_script(&args[1]),
        _ => usgae(args.len()),
    }
}

fn run_script<P: AsRef<Path>>(p: P) {
    let path = p.as_ref();
    match std::fs::read_to_string(path) {
        Ok(content) => {
            let mut env = Rc::new(RefCell::new(Env::new()));
            match evlauter::eval(&content, &mut env) {
                Ok(val) => println!("{}", val),
                Err(msg) => eprintln!("{}", msg),
            }
        }
        Err(err) => eprintln!("{}", err),
    }
}

fn run_interactive() {
    let reader = Interface::new(PROMPT).unwrap();
    reader.set_prompt(&format!("{}", PROMPT)).unwrap();

    let mut env = Rc::new(RefCell::new(Env::new()));

    while let ReadResult::Input(input) = reader.read_line().unwrap() {
        if input.eq("exit") {
            break;
        }

        match evlauter::eval(&input, &mut env) {
            Ok(val) => println!("{}", val),
            Err(msg) => eprintln!("{}", msg),
        }
    }
}

fn usgae(len: usize) {
    eprintln!("Unexpect arg size '{}'", len);
    eprintln!("Usage:");
    eprintln!("\trlisp [script_file]")
}